matchedGeometryEffect
matchedGeometryEffect establishes a geometric relationship between different views, allowing them to animate smoothly when transitioning across:
- Different layouts
- Different containers
- Different conditional render states
- Different size and position configurations
It corresponds to SwiftUI’s matchedGeometryEffect and is a component-level geometry animation system, independent of navigation.
1. API Definition
2. Core Purpose
The core purpose of matchedGeometryEffect is:
To make two views that represent the same logical element share geometry information across different layouts, producing a continuous animated transition instead of a visual jump.
This solves issues such as:
- Sudden jumps when a view moves between containers
- Abrupt size changes when expanding a card
- Layout discontinuity between list and detail views
- Teleport-like behavior of tab indicators
3. Parameter Details
3.1 id — Geometry Matching Identifier
-
Identifies which views belong to the same geometry group.
-
Only views with the same
idinside the samenamespacewill match. -
Typically derived from:
- Model identifiers
- Index values
- Stable business keys
Rules:
- The
idmust remain stable during animation. - One
idcan have only oneisSource = trueat any moment.
3.2 namespace — Geometry Namespace
- Defines the animation scope.
- Even if two views share the same
id, they will not animate unless thenamespaceis also the same. - Must be created and injected via
NamespaceReader.
Rules:
- Source and target must use the exact same namespace instance.
- Cross-namespace matching is not allowed.
3.3 properties — Geometry Properties to Match
Default:
Meaning:
Guidelines:
- Use
"frame"for natural transitions - Use
"position"for indicators and sliding highlights - Use
"size"for zooming and expansion effects
3.4 anchor — Animation Anchor Point
Default:
Controls how the geometry alignment is calculated during animation.
Common values:
"center""topLeading""topTrailing""bottomLeading""bottomTrailing"
Usage examples:
- Expanding a card from the top-left
- Zooming an avatar from the top-right
- Sliding a panel upward from the bottom
3.5 isSource — Geometry Data Provider
Default:
Meaning:
Standard pattern:
- Original view →
isSource: true - Target view →
isSource: false
If omitted:
- The first appearing view becomes the source by default.
4. Minimal Working Example (Position + Size Matching)
This example shows a circle moving and scaling smoothly between two containers.
Behavior
-
The same logical circle:
- Moves downward
- Grows in size
- Maintains continuous animation
-
No visual teleportation occurs
5. Position-Only Matching (Tab Indicator)
Used for:
- Tab selection indicators
- Sliding highlights
- Moving selection backgrounds
6. Size-Only Matching (Zoom Animation)
Suitable for:
- Avatar zooming
- Card expansion
- Press feedback animations
7. Multi-Element Matching (Card → Detail View)
Effect:
- Image and title animate together
- Transition from compact card to expanded detail layout
- No navigation system required
8. Key Usage Rules
-
namespacemust be identical -
idmust be identical -
At any time:
- One
id→ only oneisSource = true
- One
-
Default behavior:
-
Source and target must switch within the same render cycle
-
If both views are marked as
isSource: true, results are undefined -
Live Activity and Widget environments do not fully support matched geometry animations
9. Suitable Use Cases
Recommended:
- Tab indicators
- Card-to-detail transitions
- Image zoom previews
- List selection animations
- Split-view selection synchronization
Not recommended:
- High-frequency updating lists
- Large grids with many simultaneous matches
- Real-time chart rendering
